#include<iostream>
#include<vector>
#include<map>

using namespace std;

//struct Point
//{
//	int _x; 
//	int _y;
//
//	//构造函数
//	Point(int x, int y)
//		: _x(x)
//		, _y(y)
//	{}
//};
//
//
//int main()
//{
//	//C++11扩大了用大括号括起的列表(初始化列表)的使用范围，使其可用于所有的内置类型和用户自定义的类型，
//	//使用初始化列表时，可添加等号(=)，也可不添加。
//	
//	// 内置类型变量
//	int c = { 2 };
//	int b{ 2 }; // 赋值符号也可以省略
//	// 数组
//	int arr1[5]{ 1,2,3,4,5 }; // 赋值符号也可以省略
//	// 自定义结构体
//	Point p1{ 1, 2 };
//
//	// *动态数组，在C++98中不支持
//	int* arr3 = new int[5]{ 1,2,3 }; //后两个按数组初始化的特性，会初始化为0
//	
//	Point* ptr = new Point[2]{ { 1, 2 }, { 3, 4 } };//因为沿袭自C语言的特性，该行代码不用写构造函数也可以完成初始化，
//	                                                //但是如果写了构造函数就会进行多参数构造函数的隐式类型转换，此时如果用explicit进行阻止就会编译报错。
//	Point p2{ 3, 4 };//该行代码不用写构造函数也可以完成初始化，因为该特性是沿袭自C语言的。
//					 
//	Point p3(5, 6);//该行没构造函数无法通过编译，这里其实是C++11支持的多参数构造函数的隐式类型转换，可以用explicit阻止。	
//	//总结：最好写一个对应的构造函数
//
//	// 标准容器
//	vector<int> v1 = { 1,2,3,4,5 };
//	vector<int> v2{ 1,2,3,4,5 };
//	map<int, int> m{ {1,1}, {2,2,},{3,3},{4,4} };	
//	//// typeid()的使用
//	//cout << typeid(m).name() << endl;
//	//int x1 = 1;
//	//const int y1 = 2;
//	//cout << typeid(x1).name() << " " << typeid(y1).name() << endl; 
//	////typeid().name()拿到的类型不区分是否为const变量，故此处取到的x与y的类型都是int
//
//	// decltype()的使用
//	int x = 1;
//	double y = 2.2;
//	//用decltype推演x*y的实际类型，作为定义c的类型。
//	decltype(x * y) ret;
//	//推导x的类型，作为定义z的类型。
//	decltype(x) z; 
//	//用decltype推导出来的类型还可以用来做模板参数（这个auto无法替代）
//	vector<decltype(x)> v;
//
//	return 0;
//}

int fmin(int x, int y)
{
	return x > y ? y : x;
}

int main()
{
	//交叉引用:
	//左值引用能否引用右值？右值引用能否引用左值？
	
	int x = 1, y = 2;
	//常见右值	
	10;
	x + y;
	fmin(x, y);

	//常见左值
	int* p = new int(0);
	int b = 1;
	const int c = 2;

	//左值引用能否引用右值？ --- 不能直接引用，但是const左值引用可以引用右值
	const int& r1 = 10;
	const int& r2 = x + y;
	const int& r3 = fmin(x, y);

	//右值引用能否引用左值？ --- 不能直接引用，但是右值引用可以引用move以后的左值
	int*&& rr1 = move(p);
	int&& rr2 = move(*p);
	int&& rr3 = move(b);
	const int&& rr4 = move(c);

	//需要注意的是右值是不能取地址的，但是给右值取别名后，会导致右值被存储到特定的位置，且可以取到该位置的地址。
	//eg:
	10; //不能取字面常量10的地址
	int&& rr = 10;
	int*&& prr = &rr; //rr引用过后可以对rr取地址
	*prr = 9; //也可以修改rr	

	return 0;
}